package cd.casic.server.utils;
import cd.casic.server.entity.JenkinsPlugin;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
import java.util.List;


public class JenkinsPluginApiClient {
    private static final Logger logger = LoggerFactory.getLogger(JenkinsPluginApiClient.class);
    private final String jenkinsUrl;
    private final String username;
    private final String apiToken;
    private final HttpClient httpClient;

    public JenkinsPluginApiClient(String jenkinsUrl, String username, String apiToken) {
        // 确保 jenkinsUrl 以斜杠结尾
        this.jenkinsUrl = jenkinsUrl.endsWith("/") ? jenkinsUrl : jenkinsUrl + "/";
        this.username = username;
        this.apiToken = apiToken;
        this.httpClient = createAuthenticatedClient();
    }

    public List<JenkinsPlugin> getInstalledPlugins() throws IOException {
        List<JenkinsPlugin> plugins = new ArrayList<>();
        String apiUrl = jenkinsUrl + "/pluginManager/api/json?depth=1";
        HttpGet request = new HttpGet(apiUrl);
        request.setHeader(HttpHeaders.ACCEPT, "application/json");

        // 显式设置基本认证头
        String auth = username + ":" + apiToken;
        String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8));
        request.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + encodedAuth);

        // 添加CSRF令牌（如果需要）
        String crumb = getCrumb();
        if (crumb != null) {
            request.setHeader("Jenkins-Crumb", crumb);
        }

        HttpResponse response = httpClient.execute(request);
        int statusCode = response.getStatusLine().getStatusCode();

        if (statusCode == 200) {
            String jsonString = EntityUtils.toString(response.getEntity());
            JSONObject json = new JSONObject(jsonString);
            JSONArray pluginArray = json.getJSONArray("plugins");

            for (int i = 0; i < pluginArray.length(); i++) {
                JSONObject pluginJson = pluginArray.getJSONObject(i);
                plugins.add(parsePlugin(pluginJson));
            }
        } else {
            String responseBody = EntityUtils.toString(response.getEntity());
            logger.error("请求失败，状态码: {}, 响应体: {}", statusCode, responseBody);
            throw new IOException("请求失败，状态码: " + statusCode);
        }

        return plugins;
    }


    /**
     * 搜索可用插件（包括未安装的）todo
     */
    public List<JenkinsPlugin> getAvailablePlugins(String query) throws IOException, URISyntaxException {

        List<JenkinsPlugin> plugins = new ArrayList<>();

        // 使用 updateCenter 端点获取插件列表
        String apiUrl = jenkinsUrl + "updateCenter/api/json?depth=1";

        HttpGet request = new HttpGet(apiUrl);
        request.setHeader(HttpHeaders.ACCEPT, "application/json");

        // 设置认证头
        String auth = username + ":" + apiToken;
        String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8));
        request.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + encodedAuth);

        HttpResponse response = httpClient.execute(request);
        int statusCode = response.getStatusLine().getStatusCode();


        if (statusCode == 200) {
            String json = EntityUtils.toString(response.getEntity());
            JSONObject jsonObject = new JSONObject(json);

            // 检查 updateCenter 响应结构
            if (jsonObject.has("plugins")) {
                JSONArray pluginArray = jsonObject.getJSONArray("plugins");

                for (int i = 0; i < pluginArray.length(); i++) {
                    JSONObject pluginJson = pluginArray.getJSONObject(i);

                    // 从 updateCenter 响应中提取插件信息
                    String shortName = pluginJson.getString("name");
                    String version = pluginJson.getString("version");
                    String longName = pluginJson.optString("displayName", shortName);
                    String description = pluginJson.optString("longName", longName);
                    String requiredCore = pluginJson.optString("requiredCore", "");

                    // 构建插件对象
                    plugins.add(new JenkinsPlugin(
                            shortName, version, longName, description,
                            requiredCore, false, false, false));
                }
            } else {
                logger.warn("API 响应中缺少 plugins 字段: {}", json);
            }
        } else {
            throw new IOException("搜索失败，状态码: " + statusCode);
        }


        return plugins;
    }
    /**
     * 下载并安装插件 todo
     */
    public void installPlugin(String shortName) throws IOException {
        String apiUrl = jenkinsUrl + "pluginManager/installNecessaryPlugins";

        HttpPost request = new HttpPost(apiUrl);
        request.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");

        String crumb = getCrumb();
        if (crumb != null) {
            request.setHeader(crumb.split(": ")[0], crumb.split(": ")[1]);
        }

        // 构建请求体，指定要安装的插件
        StringEntity requestEntity = new StringEntity(
                "plugin." + shortName + "=true",
                ContentType.APPLICATION_FORM_URLENCODED
        );
        request.setEntity(requestEntity);

        HttpResponse response = httpClient.execute(request);
        int statusCode = response.getStatusLine().getStatusCode();

        if (statusCode != 200 && statusCode != 201) {
            throw new IOException("安装插件失败，状态码: " + statusCode);
        }

        // 安装通常是异步的，可能需要检查安装状态
        logger.info("插件 {} 安装请求已提交", shortName);
    }


    /**
     * 删除插件 todo
     */
    public void deletePlugin(String shortName) throws IOException {
        String apiUrl = jenkinsUrl + "pluginManager/plugin/" + shortName + "/doUninstall";

        HttpPost request = new HttpPost(apiUrl);

        String crumb = getCrumb();
        if (crumb != null) {
            request.setHeader(crumb.split(": ")[0], crumb.split(": ")[1]);
        }

        HttpResponse response = httpClient.execute(request);
        int statusCode = response.getStatusLine().getStatusCode();

        if (statusCode != 200 && statusCode != 201) {
            throw new IOException("删除插件失败，状态码: " + statusCode);
        }

        logger.info("插件 {} 删除请求已提交", shortName);
    }


    /**
     * 解析插件 JSON 对象
     */
    private JenkinsPlugin parsePlugin(JSONObject pluginJson) {
        String shortName = pluginJson.getString("shortName");
        String version = pluginJson.getString("version");
        String longName = pluginJson.getString("longName");
        String description = pluginJson.optString("description", longName);
        String requiredCore = pluginJson.optString("requiredCore", "");
        boolean active = pluginJson.optBoolean("active", false);
        boolean enabled = pluginJson.optBoolean("enabled", false);
        boolean hasUpdate = pluginJson.optBoolean("hasUpdate", false);



        return new JenkinsPlugin(shortName, version, longName, description,
                requiredCore, active, enabled, hasUpdate);
    }

    /**
     * 创建带认证的 HTTP 客户端
     */
    private HttpClient createAuthenticatedClient() {
        // 创建凭证提供程序
        CredentialsProvider provider = new BasicCredentialsProvider();
        // 设置用户名和API Token作为凭证
        UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, apiToken);
        provider.setCredentials(AuthScope.ANY, credentials);

        // 创建HttpClient并设置凭证提供程序
        return HttpClients.custom()
                .setDefaultCredentialsProvider(provider)
                .build();
    }


    private String getCrumb() throws IOException {
        HttpGet request = new HttpGet(jenkinsUrl + "crumbIssuer/api/json");

        // 添加认证头到 CSRF 请求
        String auth = username + ":" + apiToken;
        String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8));
        request.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + encodedAuth);

        HttpResponse response = httpClient.execute(request);

        if (response.getStatusLine().getStatusCode() == 200) {
            String json = EntityUtils.toString(response.getEntity());
            JSONObject crumbJson = new JSONObject(json);
            return crumbJson.getString("crumbRequestField") + ": " + crumbJson.getString("crumb");
        } else {
            logger.warn("获取 CSRF 令牌失败，状态码: {}", response.getStatusLine().getStatusCode());
            return null;
        }
    }

}
